package cn.com.idmy.id.segment;

import cn.com.idmy.id.segment.model.IdState;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.math.BigDecimal;
import java.math.RoundingMode;

@Data
@Slf4j
public class Segment {
    private long minId;
    private volatile long curId;
    private long maxId;
    private static final VarHandle CURRENT_ID_HANDLE;

    static {
        try {
            var lookup = MethodHandles.lookup();
            CURRENT_ID_HANDLE = lookup.findVarHandle(Segment.class, "curId", long.class);
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    @Nullable
    public IdState nextId(int num) {
        while (true) {
            long curId = this.curId;
            if (curId == maxId) {
                break;
            }
            long nextId = curId + num;
            if (maxId >= nextId && compareAndSwapCurId(curId, nextId)) {
                return IdState.builder().curId(curId).minId(curId).maxId(nextId).build();
            }
            long diff = maxId - curId;
            if (nextId > maxId && diff > 0 && compareAndSwapCurId(curId, maxId)) {
                return IdState.builder().curId(curId).minId(curId).maxId(maxId).build();
            }
        }
        return null;
    }

    @NotNull
    public BigDecimal percent() {
        //初始状态
        if (maxId == 0) {
            return new BigDecimal("1.00");
        } else {
            return new BigDecimal(curId - minId).divide(new BigDecimal(maxId - minId), 3, RoundingMode.UP);
        }
    }

    private boolean compareAndSwapCurId(long curId, long nextId) {
        // 使用VarHandle的CAS操作替代Unsafe.compareAndSwapLong
        return CURRENT_ID_HANDLE.compareAndSet(this, curId, nextId);
    }
}